
在現代動態設計中,過程的流暢性往往比最終的結果更能吸引使用者的目光。
Vue 的過渡類別不僅能幫助我們設計出精美的動效,更能將每一個動作細膩地表現出來,讓動態不再僅僅是視覺上的變化,而是充滿韻律與故事感的藝術。
為什麼過渡類別如此重要?
過渡類別可以讓元素的進場和離場變得更自然且引人入勝,不僅是設計的點綴,更是使用者體驗的升級。
例如在商業網站中,產品展示、創意作品集等應用場景,這些過渡效果都能讓頁面切換更順暢,並增添整體的精緻感,增加瀏覽率。
Page Transition 滑頁效果是現代網站中不可或缺的過渡技巧之一。
無論是產品展示、電商平台還是創意作品集,這些過渡類別總是能在關鍵時刻出現,讓頁面切換更順。
當用得恰到好處,不僅讓畫面更靈動,還能給人一種高質感的視覺享受!

檔案架構
首先是PageTransition.vue父元件
PageTransitionStart.vue
PageTransitionNext.vue
PageTransitionEnd.vue,再下一頁會回到第一頁主要程式碼(PageTransition.vue)
<script lang="ts" setup>
import { shallowRef, computed, defineAsyncComponent } from 'vue';
// 定義我們的每頁component
enum Pages {
  Start = 'start',
  Next = 'next',
  End = 'end', // 新增頁面作為示例
}
// 定義頁面元件與背景顏色的配置
const pageConfig = {
  [Pages.Start]: {
    component: defineAsyncComponent(() => import('./PageTransitionStart.vue')),
    color: 'bg-[#f1c40f]'
  },
  [Pages.Next]: {
    component: defineAsyncComponent(() => import('./PageTransitionNext.vue')),
    color: 'bg-[#e67e22]'
  },
  [Pages.End]: {
    component: defineAsyncComponent(() => import('./PageTransitionEnd.vue')), 
    color: 'bg-green-300'
  }
};
const page = shallowRef(Pages.Start);
// 使用 pageConfig 獲取對應的元件和背景顏色
const getComponent = computed(() => pageConfig[page.value].component);
const containerBgColor = computed(() => pageConfig[page.value].color);
const changePage = (newPage: Pages) => {
  page.value = newPage;
};
</script>
<template>
  <div :class="['relative w-full h-screen overflow-hidden', containerBgColor]">
    <transition name="slide" mode="out-in">
      <component :is="getComponent" @change-page="changePage" />
    </transition>
  </div>
</template>
<style scoped>
.slide-enter-from {
  transform: translateX(100%);
}
.slide-enter-active, .slide-leave-active {
  position: absolute;
  width: 100%;
  transition: transform 0.5s ease;
}
.slide-leave-to {
  transform: translateX(-100%);
}
.slide-enter-to, .slide-leave-from {
  transform: translateX(0);
}
</style>
<style scoped>
.slide-enter-from {
  transform: translateX(100%);
}
.slide-enter-active, .slide-leave-active {
  position: absolute;
  width: 100%;
  transition: transform 0.5s ease;
}
.slide-leave-to {
  transform: translateX(-100%);
}
.slide-enter-to, .slide-leave-from {
  transform: translateX(0);
}
</style>
進場流程
元素從右側滑入 (slide-enter-from) → 過渡過程中保持絕對位置與寬度 (slide-enter-active) → 最終到達正中位置 (slide-enter-to)。
離場流程
元素從正中開始 元素從正中開始 (slide-leave-from) → 過渡過程中保持絕對位置與寬度 (slide-leave-active) → 最後滑出到左側 (slide-leave-to)
PageTransitionStart.vue
<script lang="ts" setup>
//定義事件 defineEmits
const emit = defineEmits(['change-page']);
</script>
<template>
<transition name="slide">
  <div class="grid w-full grid-cols-[repeat(auto-fit,_minmax(400px,_1fr))]">
    <transition name="fade">
      <div
        class="grid h-screen items-center justify-center bg-[var(--bg-color)]"
        :style="{ '--bg-color': '#f1c40f' }"
      >
      // 換頁方法
      // 當按鈕被點擊時,`@click` 會監聽到這個事件並執行 `emit('change-page', 'next')`
        <button
          @click="emit('change-page', 'next')"
          class="btn-jittery text-8 font-mono bg-transparent
             text-white 
             border-3 border-solid border-white rounded-full px-8 py-3 
             outline-none cursor-pointer tracking-[2px]
             animate-[jittery_4s_infinite] hover:animate-[heartbeat_0.2s_infinite]
             "
        >
          Start !
        </button>
      </div>
    </transition>
  </div>
</transition>
</template>
<style>
/* Vue Transition Styles */
.fade-enter-active,
.fade-leave-active {
  transition: all 0.2s ease-in-out;
}
.fade-enter-from,
.fade-leave-to {
  opacity: 0;
}
@keyframes jittery {
  0%, 50% { transform: scale(1); }
  10% { transform: scale(0.9); }
  15% { transform: scale(1.15); }
  20% { transform: scale(1.15) rotate(-5deg); }
  25% { transform: scale(1.15) rotate(5deg); }
  30% { transform: scale(1.15) rotate(-3deg); }
  35% { transform: scale(1.15) rotate(2deg); }
  40% { transform: scale(1.15) rotate(0); }
}
@keyframes heartbeat {
  50% {
    transform: scale(1.1);
  }
}
</style>
PageTransitionNext.vue
//.... 其他重複先省略
    <transition name="fade">
      <div
        class="grid h-screen items-center justify-center bg-[var(--bg-color)]"
        :style="{ '--bg-color': '#e67e22' }"
      >
        <button
          @click="emit('change-page', 'start')"
          class="btn-jittery text-8 font-mono bg-transparent
             text-white 
             border-3 border-solid border-white rounded-full px-8 py-3 
             outline-none cursor-pointer tracking-[2px]
             animate-[jittery_4s_infinite] hover:animate-[heartbeat_0.2s_infinite]
             "
        >
          End !
        </button>
      </div>
    </transition>
//....
PageTransitionEnd.vue
//....與前面兩頁一樣,僅提供差異處
// 定義此頁背景色
<div class="grid h-screen items-center justify-center bg-[var(--bg-color)]"
	:style="{ '--bg-color': '#e67e22' }"
>	
// emit('change-page','start') 帶入第一頁參數,下一頁就又回到第一頁了
	<button @click="emit('change-page', 'start')" class="..."></button>
Vue 的過渡類別的執行過程,主要應用於 初始化與加載 和 結尾與退出 這兩個核心階段。
中間的 瀏覽與互動階段 會使用 CSS 動畫(@keyframes)或是JavaScript、GSAP等等來進行。
進場動效順序
v-enter-from → v-enter-active → v-enter-to
離場動效順序
v-leave-from → v-leave-active → v-leave-to
v-enter-from 前面的v就是我們自定義的class名稱。
進場動效
初始化開始
v-enter-from:元素剛插入時的初始狀態(通常是隱藏的狀態)。這是動效的起點,常使用 CSS 設置透明度為 0 或將元素移出視窗範圍。活動狀態
v-enter-active:進場動效進行中的狀態,從元素插入到動效完成的整個過程。這裡可調整動效的時間、延遲和緩動曲線,例如:transition: all 0.5s ease-in-out;。動效完成
v-enter-to:進場動效的結束狀態。這個類別在動效的最後應用,代表元素已完全顯示。離場動效
初始狀態
v-leave-from:觸發離場動效時的初始狀態(通常是元素顯示的狀態)。應用於動效開始時。活動狀態
v-leave-active:離場動效進行中的狀態,應用於動效的整個過程中。可設置離場動效的時間、延遲和緩動曲線。動效完成
v-leave-to:離場動效的結束狀態。這個類別在離場動效的第一幀後應用,並在動效結束時移除,通常代表元素隱藏的狀態。掌握 Vue 過渡類別後,你會發現這不僅僅是動效工具,而是一種設計語言,讓你在網站設計上能有更多創意的表現空間。
希望你能夠將這些過渡類別運用到你的專案中,並持續探索動態設計的無限可能。